//
//  VideoPlayer.swift
//  videoPlayerSwift
//
//  Created by xwl on 2019/3/6.
//  Copyright © 2019年 xuwanliang. All rights reserved.
//

import Foundation
import AVKit
import AVFoundation

protocol VideoPlayerDelegate {
    
    func videoBuffer(_ pixelBuffer: CVPixelBuffer!)
}

class MyVideoPlayer: NSObject, AVPlayerItemOutputPullDelegate, AVCaptureVideoDataOutputSampleBufferDelegate{
    
    var m_player: AVPlayer! = nil
    var playerItem: AVPlayerItem! = nil
    var delegate: VideoPlayerDelegate? = nil
    var m_URL:URL? = nil
    var m_VideoList:[String]? = nil
    var m_videoOutput:AVPlayerItemVideoOutput! = nil
    var m_displayLink: CADisplayLink! = nil
    required init(_ delegate: VideoPlayerDelegate) {
        super.init()
        self.delegate = delegate
        print("DocumetnPath \(DocumetnPath!)")
        
        m_displayLink = CADisplayLink(target: self, selector: #selector(displayLinkCallback))
        m_displayLink.add(to: .current, forMode: .default)
        m_displayLink.isPaused = true
        
        getLocalVideoList()
        initPlayer()
    }
    
    @objc func displayLinkCallback(sender: CADisplayLink){
        
        let nextVSync = sender.timestamp + sender.duration
        let outputItemTime = self.m_videoOutput.itemTime(forHostTime: nextVSync)
        //print("nextVSync ", nextVSync)
        if(self.m_videoOutput.hasNewPixelBuffer(forItemTime: outputItemTime)){
            
            //print("outputItemTime ", outputItemTime.seconds)
            var pixelBuffer: CVPixelBuffer! = nil
            pixelBuffer = self.m_videoOutput.copyPixelBuffer(forItemTime: outputItemTime, itemTimeForDisplay: nil)
            
            self.delegate?.videoBuffer(pixelBuffer)
        }
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "status" {
            switch self.playerItem.status{
            case .readyToPlay:
                print("readyToPlay")
                play()
            case .failed:
                print("failed")
            case.unknown:
                print("unkonwn")
            }
        }else if keyPath == "loadedTimeRanges"{
            let loadTimeArray = self.playerItem.loadedTimeRanges
            //获取最新缓存的区间
            let newTimeRange : CMTimeRange = loadTimeArray.first as! CMTimeRange
            let startSeconds = CMTimeGetSeconds(newTimeRange.start);
            let durationSeconds = CMTimeGetSeconds(newTimeRange.duration);
            let totalBuffer = startSeconds + durationSeconds;//缓冲总长度
            print("当前缓冲时间: ",Int(totalBuffer/3600.0),":",Int(totalBuffer/60.0), ":", Int(totalBuffer)%60)
            
            let asserts = self.playerItem.asset
            let tracks = asserts.tracks(withMediaType: .video)
            for track in tracks{
                print("video info: \(track.naturalSize)")
            }
            
        }else if keyPath == "playbackBufferEmpty"{
            print("正在缓存视频请稍等")
        }
        else if keyPath == "playbackLikelyToKeepUp"{
            print("缓存好了继续播放")
            play()
        }
    }
    
    func play(){
        m_displayLink.isPaused = false
        self.m_player.play()
    }
    
    deinit {
        self.playerItem.removeObserver(self, forKeyPath: "status", context: nil)
        self.playerItem.removeObserver(self, forKeyPath: "loadedTimeRanges", context: nil)
    }
    
    func initPlayer()
    {
        if(m_VideoList?.count == 0){
            print("no media file")
            return
        }
        
        let url = URL(fileURLWithPath: DocumetnPath! + "/" + (m_VideoList?[0])!)
        print("url: \(String(describing: url.absoluteString))")
        self.playerItem = AVPlayerItem(url: url)
        self.playerItem.addObserver(self, forKeyPath: "loadedTimeRanges", options: .new, context: nil)
        self.playerItem.addObserver(self, forKeyPath: "status", options: .new, context: nil)
        
        let pixelBufferAttributes = [ kCVPixelBufferPixelFormatTypeKey as String : NSNumber(value: kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)]
        m_videoOutput = AVPlayerItemVideoOutput(pixelBufferAttributes: pixelBufferAttributes)

        m_videoOutput.setDelegate(self, queue: DispatchQueue.main)
        self.playerItem.add(m_videoOutput)
        
        self.m_player = AVPlayer(playerItem: self.playerItem)
        
        NotificationCenter.default.addObserver(self, selector: #selector(playToEndTime), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: nil)
    }
    
    @objc func playToEndTime(){
        print("播放完成")
    }
    
    func getLocalVideoList(){
        
        //let filePaths = getAllFilePath(DocumetnPath!)
        m_VideoList = findFiles(path: DocumetnPath!, filterTypes: ["mp4"])
        for file in m_VideoList ?? []{
            print("file: \(file)")
        }
    }

}
